【他山之石】人类早期驯服野生机器学习模型的珍贵资料
“他山之石,可以攻玉”,站在巨人的肩膀才能看得更高,走得更远。在科研的道路上,更需借助东风才能更快前行。为此,我们特别搜集整理了一些实用的代码链接,数据集,软件,编程技巧等,开辟“他山之石”专栏,助你乘风破浪,一路奋勇向前,敬请关注。
地址:https://www.zhihu.com/people/zijie0
阅读建议
对于初级算法工程师,希望了解基础的算法建模流程的,可以主要阅读1~5部分。 从第6部分开始是更深入的通过数据分析来进行模型调优的一些介绍,以及后续的测试,工程化,上线的简介,比较适合有经验的算法工程师阅读。
01
清晰的优化指标 高质量Pipeline 明确的实验设计 深入的结果分析
02
2.1 什么是一个好的指标
Actionable,可以指导具体行为。 Accessible,简单,容易理解。 Auditable,可以进行验证。
2.2 机器学习项目中的指标
组织目标,例如增加整个公司的收入,降低成本,或者对社会的整体贡献等。一般会比较宏观,与具体技术的距离相对较远。另外这些指标收到的影响因素也有很多,内外部因素都有。在技术项目实现周期,到能影响到组织目标的变化过程会非常缓慢。因此一般很难直接优化这个指标。 业务指标,相对组织目标来说会更加具体和可衡量。注意在这个层面我们经常碰到一些情况是模型输出预测是否符合用户预期,这种较为模糊的指标定义往往难以衡量与改进。因此必须与用户沟通,制定出明确可量化的指标来进行衡量。这个维度的指标也经常会比较复杂,从技术层面来看可能难以直接优化。 模型指标,为了能快速迭代实验,我们往往需要深入理解前面的组织目标,业务指标,再转化为模型可以直接优化的指标,例如mae损失函数等。但这里也需要非常小心,模型指标可能并未反映用户的真实感受,或者与最终的业务目标有一些差距。
03
分析:模型问题是什么? 提出假设:可能的根源问题是什么? 设计实验:改进方案是什么? 执行与验证:改进方案是否有效? 循环迭代
3.1 问题分类
代码实现中的bug。对于机器学习pipeline来说,很多情况下即使有隐藏的bug,程序也完全能跑通。这对问题排查造成了更大的困扰。 超参数设置不合理。很多模型对各类超参数的设置比较敏感,需要针对不同的问题和表现进行超参数的调整。 数据相关问题。数据量不足,分布不均衡,出现错误的标签,缺少特定信息,有概念漂移问题等。 模型选择问题。针对特定的问题及数据情况,我们需要选择合适的模型。
3.2 整体流程
从简单的pipeline开始,例如选择最简单的规则,或者基础模型。以深度学习模型为例,我们可以选择最基础的MLP模型,adam优化方法,不加任何regularization,使用标准归一化方法,选取一个子集数据进行尝试。 实现并跑通pipeline。确保模型能够运行,并在小数据集上overfit,或复现一些已知结果。 评估并分析结果。后续会详细介绍分析手段方法。 参数调优。对模型的各种参数,模型结构进行各种调整。 数据与模型调优。修复数据中的问题,做数据增强,引入不同类型的数据,收集更多数据,或者特征工程预处理方面的操作。模型方面可以使用更加高级/复杂的模型结构,引入ensemble等。
04
4.1 Pipeline
4.2 版本管理
数据版本,如果使用的产品带数据版本,直接使用即可。否则可以考虑用sha1等文件校验码来记录数据的版本信息。 代码版本,对于库函数这类有git管理部分的代码,可以直接使用git的版本号。对于临时的notebook文件,可以每天做一个notebook版本的备份。对于重要结果,例如当前最好效果,也可以随时做版本备份。 参数配置,大多数情况下,参数配置可以在代码或者数据的版本中cover。但需要额外注意使用了外部配置文件的情况,对于这些配置文件,也需要与实验的其它运行组成来一起管理(例如放在同一个文件夹下)。 模型版本,对于模型训练非常耗时的场景,训练出来的模型也需要进行版本管理,以便于后续的分析与重用。
05
5.1 数据流验证
Tensor shape错误 预处理错误 Loss function错误 数据中有NaN/Inf等值 没有正确的设置训练模式,或其它框架相关常见错误 参数或数据处理问题导致的OOM 库版本不匹配导致的奇怪exception
使用标准化的流程pipeline,比如框架内置方法,或者自己整理的针对某类问题的标准receipe。 搜索StackOverflow,Github上相关问题,寻求解决方案。 使用debugger和profiler进行深入调试。 借助一些专用工具来辅助排查,例如tensor-sensor[4]。
5.3 在小数据集上过拟合
误差不降反升 误差爆炸 误差震荡 误差停留在一个高位无法下降
误差上升的可能原因,学习率太高,loss function定义错误 误差爆炸的可能原因,学习率太高,各种数值操作的问题,如exp,log,除法等 误差震荡的可能原因,学习率太高,原始数据问题如数据错位,预处理bug等,可以进一步通过结果分析定位 误差停留在一个高位,可能由于学习率太低,优化器相关设置,正则项过大,模型过于简单,loss function欠佳,部分数据有错误,没有做数据归一化,缺乏有效特征等
5.4 模型参数搜索
5.5 后续深入优化
06
构建有效模型的关键是能够迅速且准确的定位到当前模型失败的原因具体是什么。这也是结果分析的主要目标。
模型当前问题,例如在节假日期间,办公型门店的预测销量不准。 各个问题导致的误差占比,例如上述问题在总体误差中占了12%。 问题对应的典型数据集,例如我们可以收集一系列节假日,办公型门店的历史数据,用于后续调优改进的检验集。
模型的错误类型有哪些,是否能在目前的优化指标中反映出来。 用户真实体验如何。 模型错误可能导致的最严重后果是什么。
6.1 数据分析
6.2 模型指标分析
6.3 Generalize模型问题
6.4 模型报告
6.5 误差分析深入
6.5.1 误差分类
Mislabeling errors,标签错误。即原始的训练数据里就有问题,例如数据漏传,数据处理错误等。 Learner errors,优化错误或目标函数引入的误差,例如正则项。通过修改正则项,检查是否可以在目标函数error与泛化error之前取得平衡。 Representation errors,特征不足,或模型表达能力不足。技术上无法与mislabeling error区分,可以使用consistent learner(无正则项的lr,1-nn),找到invalidation set人工确认。 Boundary errors,数据不足。泛化错误。检测方式:将数据加入训练集后,看错误是否仍然存在。Uncertainty sampling for active learning也是基于这个思想。
使用无正则项的学习器(1-NN, LR),修复label error(correct label)和representation error(add feature),反复迭代。 验证boundary error,通过加入正则项来平衡泛化误差与learner error。
6.5.2 Identifying Unknown Unknowns
首先获取需要调查的数据集X,例如回归问题,选择误差top 10000条,或者分类问题,选择confidence很高但预测错误的条目。 候选特征pattern集合Q,通过频繁项挖掘,获取到调查数据集X中特征组合的频繁项。 开始迭代搜寻分割条件,其中pattern q来自于集合Q,计算X中符合q的条目数/g(q),取argmax时的q值。 将第三步中找到的q加入到partition条件集合P中,同时将其从候选集合Q中移除,另外也将q覆盖的条目从X中移除,继续第3步,直到X中所有条目都被覆盖。 最终的集合P就是partition方案,如果一个条目属于多个q,则取距离中心最近的那个q。
6.5.3 Error Analysis Visualization
分析error sample,构建起误差背后共通特性的DSL描述。 将上述的DSL描述作为filter,apply到全量数据上,评判误差占比。 使用conterfactual方法来分析产生误差的具体原因。
07
08
09
这个从成熟软件系统中汲取营养的想法还是很有想象空间的。延展一下联想到我们做算法的debugging,非常缺少类似Linux, JDK下各类tracing工具。所以软件工程的排查调优,一般来说都是能用工具确定性的抓到整个系统到底是如何在运行的,从应用层一直drill down到系统资源层都能得到相应的信息。而模型和数据的问题排查,很多时候只能在应用层改一些参数,观察这个黑盒的产出,成了所谓的“玄学”。如何能在数据,模型上开发出一套类似的tracing工具,把模型效果的排查成为相对确定性的追踪,是一个值得深入思考的方向。
从上一点延展到数据流方面,软件工程中也有很多值得借鉴的思想。例如编译器可以帮助程序员进行代码逻辑,类型等方面的自动化检查,提前发现问题。但是到了数据流这块(例如ETL),往往都只能到运行起来了才能发现问题。是否能够开发一些工具,做到数据转换逻辑和schema(可能还需要一些统计信息)结合的静态检查,来保障数据流的质量?
同理DevOps方面也有很多机器学习系统设计可以借鉴的地方,包括把数据因素结合进来,形成一套新的测试运维体系,达到持续集成,持续交付,持续调优的系统形态等(联想的有点远了……)。
[1] https://zhuanlan.zhihu.com/p/218468169
[2] https://www.deeplearning.ai/programs/
[3] https://helix-ml.github.io/
[4] https://explained.ai/tensor-sensor/index.html
[5] https://karpathy.github.io/2019/04/25/recipe/
[6] https://pair.withgoogle.com/chapter/errors-failing/
[7] https://arxiv.org/abs/1810.03993
[8] https://arxiv.org/abs/1611.05955
[9] https://arxiv.org/abs/1610.09064
[10] https://github.com/uwdata/errudite
[11] https://developers.google.com/machine-learning/guides/good-data-analysis
[12] https://pnnl.github.io/crosscheck/
[13] https://www.microsoft.com/en-us/research/uploads/prod/2018/04/AnchorViz-camera-ready.pdf
[14] https://www.microsoft.com/en-us/research/video/anchorviz-facilitating-semantic-data-exploration-and-concept-discovery-for-interactive-machine-learning-2/
[15] http://xuk.ai/darksight/
[16] https://medium.com/airbnb-engineering/https-medium-com-jonathan-parks-scaling-erf-23fd17c91166
[17] https://eng.uber.com/backtesting-at-scale/
[18] https://eng.uber.com/xp/
[19] https://github.com/intuit/wasabi
[20] https://github.com/facebook/planout
[21] https://arxiv.org/pdf/2005.01520.pdf
[22] http://sites.computer.org/debull/A19june/p59.pdf
[23] https://www.microsoft.com/en-us/research/publication/interactive-machine-teaching-a-human-centered-approach-to-building-machine-learned-models/
“他山之石”历史文章
不会强化学习,只会numpy,能解决多难的RL问题?
技术总结《OpenAI Gym》
ROC和CMC曲线的理解(FAR, FRR的理解)
pytorch使用hook打印中间特征图、计算网络算力等
Ray和Pytorch Lightning 使用指北
如何在科研论文中画出漂亮的插图?
PyTorch 源码解读之 torch.optim:优化算法接口详解
AI框架基础技术之深度学习中的通信优化
SimCLR:用于视觉表征的对比学习框架
Pytorch Autograd与计算图
tensorflow2.4性能调优最佳实践
PyTorch | DDP系列:入门教程、实现原理与源代码解析、实战与技巧
教你用PyTorch玩转Transformer英译中翻译模型!
深度学习工程技巧之网格调参
PyTorch使用预训练模型进行模型加载
更多他山之石专栏文章,
请点击文章底部“阅读原文”查看
分享、点赞、在看,给个三连击呗!